package x.java.lang;

import java.io.InputStream;
import java.io.PrintStream;
import java.util.Properties;

/**
 * @author qiangli
 *
 */
public final class System {
	private static final String JVS_SHUTDOWN_ONEXIT = "jvs.shutdown.onexit";
	
	//TODO switch between single user and multi-user mode
	
	public static int initLevel = 1;
	
	private static class SystemContext {
		private InputStream in = java.lang.System.in;

		private PrintStream out = java.lang.System.out;

		private PrintStream err = java.lang.System.err;

		private Properties properties = new Properties();
			
		public int status = 0;
		
		public SystemContext() {
			//http://java.sun.com/j2se/1.4.2/docs/api/java/lang/System.html
			//java.version Java Runtime Environment version 
			//java.vendor Java Runtime Environment vendor 
			//java.vendor.url Java vendor URL 
			//java.home Java installation directory 
			//java.vm.specification.version Java Virtual Machine specification version 
			//java.vm.specification.vendor Java Virtual Machine specification vendor 
			//java.vm.specification.name Java Virtual Machine specification name 
			//java.vm.version Java Virtual Machine implementation version 
			//java.vm.vendor Java Virtual Machine implementation vendor 
			//java.vm.name Java Virtual Machine implementation name 
			//java.specification.version Java Runtime Environment specification version 
			//java.specification.vendor Java Runtime Environment specification vendor 
			//java.specification.name Java Runtime Environment specification name 
			//java.class.version Java class format version number 
			//java.class.path Java class path 
			//java.library.path List of paths to search when loading libraries 
			//java.io.tmpdir Default temp file path 
			//java.compiler Name of JIT compiler to use 
			//java.ext.dirs Path of extension directory or directories 
			//os.name Operating system name 
			//os.arch Operating system architecture 
			//os.version Operating system version 
			//file.separator File separator ("/" on UNIX) 
			//path.separator Path separator (":" on UNIX) 
			//line.separator Line separator ("\n" on UNIX) 
			//user.name User's account name 
			//user.home User's home directory 
			//user.dir User's current working directory
			//
			properties.putAll(java.lang.System.getProperties());
			//
			//
			properties.setProperty("sun.boot.library.path","");
			properties.setProperty("java.endorsed.dirs","");
			properties.setProperty("java.library.path","");
			properties.setProperty("java.ext.dirs","");
			properties.setProperty("sun.boot.class.path","");
			////
			properties.setProperty("java.home", "/boot");
			properties.setProperty("java.class.path", "/classes/");
			//
			properties.setProperty("java.io.tmpdir", "/tmp");
			properties.setProperty("file.separator", "/");
			properties.setProperty("path.separator", ";");
			properties.setProperty("line.separator", "\n");
			//
			String user = "guest";
			properties.setProperty("user.name",user);
			properties.setProperty("user.home","/home/"+user);
			properties.setProperty("user.dir","/home/"+user);
			properties.setProperty("path", "/bin/;/bin/windows/;/sbin/");
			//
			properties.setProperty("user.country","");
			properties.setProperty("user.language","");
			properties.setProperty("user.timezone","");
			properties.setProperty("user.variant","");
			//
			properties.setProperty(JVS_SHUTDOWN_ONEXIT,"false");
		}
	}

	private static class ThreadLocalSystemContext extends
			InheritableThreadLocal<SystemContext> {
		public SystemContext initialValue() {
			return new SystemContext();
		}
	}

	private static ThreadLocalSystemContext local = new ThreadLocalSystemContext();

	private static SystemContext getContext() {
		SystemContext sc = (SystemContext) local.get();
		//java.lang.System.err.println(">>>>>>>>> "+Thread.currentThread()+" context:"+sc);
		return sc;
	}

	private System() {
	}

	public static void arraycopy(Object src, int srcPos, Object dest,
			int destPos, int length) {
		java.lang.System.arraycopy(src, srcPos, dest, destPos, length);
	}

	public static long currentTimeMillis() {
		return java.lang.System.currentTimeMillis();
	}

	public static void shutdown(int status) {
		cleanup(status);
		java.lang.System.exit(status);
	}
	
	private static void cleanup(int exitStatus) {
		SystemContext sc = getContext();
		try {
			sc.in.close();	
		} catch (Exception e) {	
		}
		try {
			sc.out.close();	
		} catch (Exception e) {	
		}
		try {
			sc.err.close();	
		} catch (Exception e) {	
		}
		sc.status = exitStatus;
	}
	
	public static void exit(int status) {
		cleanup(status);
		String soe = x.java.lang.System.getProperty(JVS_SHUTDOWN_ONEXIT,"true");
		if (Boolean.valueOf(soe).booleanValue()) {
			java.lang.System.exit(status);
		}
	}

	public static void gc() {
		java.lang.System.gc();
	}
	
	public static String getenv(String name) {
		SystemContext sc = getContext();
		return sc.properties.getProperty(name);
	}

	public static Properties getProperties() {
		SystemContext sc = getContext();
		return sc.properties;
	}

	public static String getProperty(String key) {
		SystemContext sc = getContext();
		return sc.properties.getProperty(key);
	}

	public static String getProperty(String key, String def) {
		SystemContext sc = getContext();
		return sc.properties.getProperty(key,def);
	}
	
	public static Object get(Object key) {
		SystemContext sc = getContext();
		return sc.properties.get(key);
	}

	public static SecurityManager getSecurityManager() {
		throw new RuntimeException("Not supported");
	}

	public static int identityHashCode(Object x) {
		return java.lang.System.identityHashCode(x);
	}

	public static void load(String filename) {
		throw new RuntimeException("Not supported");
	}

	public static void loadLibrary(String libname) {
		throw new RuntimeException("Not supported");
	}

	public static String mapLibraryName(String libname) {
		throw new RuntimeException("Not supported");
	}

	public static void runFinalization() {
		throw new RuntimeException("Not supported");
	}

	public static void runFinalizersOnExit(boolean value) {
		throw new RuntimeException("Not supported");
	}

	public static void setErr(PrintStream err) {
		SystemContext sc = getContext();
		sc.err = err;
	}

	public static void setIn(InputStream in) {
		SystemContext sc = getContext();
		sc.in = in;
	}

	public static void setOut(PrintStream out) {
		SystemContext sc = getContext();
		sc.out = out;
	}

	public static void setProperties(Properties props) {
		SystemContext sc = getContext();
		sc.properties = props;
	}

	public static String setProperty(String key, String value) {
		SystemContext sc = getContext();
		String oldval = sc.properties.getProperty(key);
		sc.properties.setProperty(key,value);
		return oldval;
	}
	
	public static Object set(Object key, Object value) {
		SystemContext sc = getContext();
		Object oldval = sc.properties.get(key);
		sc.properties.put(key,value);
		return oldval;
	}

	public static void setSecurityManager(SecurityManager s) {
		throw new RuntimeException("Not supported");
	}
	
	public static PrintStream err() {
		SystemContext sc = getContext();
		return sc.err;
	}

	public static InputStream in() {
		SystemContext sc = getContext();
		return sc.in;
	}

	public static PrintStream out() {
		SystemContext sc = getContext();
		return sc.out;
	}
}
